/**
 * 
 */
package com.ieasy.module.system.service;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ieasy.basic.dao.IBaseDao;
import com.ieasy.basic.model.Msg;
import com.ieasy.basic.util.BeanUtils;
import com.ieasy.basic.util.NumberUtil;
import com.ieasy.basic.util.dbutil.IDBUtilsHelper;
import com.ieasy.module.system.entity.VoteEntity;
import com.ieasy.module.system.entity.VoteRecordEntity;
import com.ieasy.module.system.web.form.VoteForm;

/**
 * @author 杨浩泉
 *
 */
@Service("voteService") @Transactional
public class VoteService implements IVoteService {

	private static Logger logger = Logger.getLogger(VoteService.class) ;
	
	@Inject
	private IBaseDao<VoteEntity> basedaoVote ;
	@Inject
	private IBaseDao<VoteRecordEntity> basedaoVoteRecord ;
	
	@Inject
	private IDBUtilsHelper dbutil;
	
	@Override
	public Msg add(VoteForm form) {
		addResetSort(form.getPid()) ;
		
		VoteEntity entity = new VoteEntity() ;
		entity.setWeight(1) ;
		entity.setCreated(new Date()) ;
		
		BeanUtils.copyNotNullProperties(form, entity) ;
		
		if (form.getPid() != null && !"".equalsIgnoreCase(form.getPid())) {
			entity.setVote(this.basedaoVote.load(VoteEntity.class, form.getPid())) ;
		}
		
		this.basedaoVote.add(entity) ;
		return new Msg(true, "添加成功！");
	}
	
	@Override
	public Msg delete(VoteForm form) {
		VoteEntity entity = this.basedaoVote.load(VoteEntity.class, form.getId()); ;
		int oldSort = entity.getWeight() ;
		String pid = (null!=entity.getVote()?entity.getVote().getId():null) ;
		del(entity) ;
		
		delResetSort(oldSort, pid) ;
		return new Msg(true, "删除成功！");
	}
	
	private void del(VoteEntity entity) {
		if (entity.getVotes() != null && entity.getVotes().size() > 0) {
			for (VoteEntity e : entity.getVotes()) {
				del(e);
			}
		}
		this.basedaoVote.delete(VoteEntity.class, entity.getId()) ;
	}

	@Override
	public Msg update(VoteForm form) {
		VoteEntity entity = this.basedaoVote.load(VoteEntity.class, form.getId()) ;
		BeanUtils.copyNotNullProperties(form, entity) ;
		entity.setModifyDate(new Date()) ;
		
		if(null != entity.getVote() && !form.getPid().equals(entity.getVote().getId())) {
			entity.setWeight(getMM(form.getPid())[1]+1) ;
		}
		if (null != form.getPid() && !"".equals(form.getPid())) {
			if(!entity.getId().equals(form.getPid())) {
				entity.setVote(this.basedaoVote.load(VoteEntity.class, form.getPid()));
			} else {
				return new Msg(false, "操作有误，父模块服务关联自己！");
			}
		}
		this.basedaoVote.update(entity) ;
		
		return new Msg(true, "修改成功！");
	}
	
	@Override
	public VoteForm get(VoteForm form) {
		VoteEntity entity = this.basedaoVote.load(VoteEntity.class, form.getId()) ;
		BeanUtils.copyNotNullProperties(entity, form) ;
		if (null != entity.getVote()) {
			form.setPid(entity.getVote().getId());
		}
		return form ;
	}

	@Override
	public List<VoteForm> tree(String pid) {
		String sql = "select t.* from ieasy_sys_vote t where t.pid is null order by t.weight asc" ;
		if(null != pid && !"".equals(pid.trim()))
			sql = "select t.* from ieasy_sys_vote t where t.id='"+pid+"'" ;
		
		List<VoteForm> list = this.basedaoVote.listSQL(sql, VoteForm.class, false) ;
		List<VoteForm> forms = new ArrayList<VoteForm>() ;
		for (VoteForm e : list) {
			try {
				//总票数
				Map<String, Object> map = this.dbutil.getQr().query("select SUM(t.sum) totalVote from ieasy_sys_vote t where t.pid=?", new MapHandler(), new Object[]{e.getId()}) ;
				if(null != map.get("totalVote")) {
					e.setTotalVote(Integer.parseInt(map.get("totalVote").toString()));
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			
			forms.add(recursive(e));
		}
		
		return forms;
	}
	
	@Override
	public List<VoteForm> viewVote(String pid) {
		String sql = "select t.* from ieasy_sys_vote t where t.pid is null and t.status=false order by t.weight asc" ;
		if(null != pid && !"".equals(pid.trim()))
			sql = "select t.* from ieasy_sys_vote t where t.id='"+pid+"' and t.status=false" ;
		
		List<VoteForm> list = this.basedaoVote.listSQL(sql, VoteForm.class, false) ;
		List<VoteForm> forms = new ArrayList<VoteForm>() ;
		for (VoteForm e : list) {
			try {
				//总票数
				Map<String, Object> map = this.dbutil.getQr().query("select SUM(t.sum) totalVote from ieasy_sys_vote t where t.pid=?", new MapHandler(), new Object[]{e.getId()}) ;
				if(null != map.get("totalVote")) {
					Integer totalVote = Integer.parseInt(map.get("totalVote").toString()) ;
					e.setTotalVote(totalVote);
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			
			forms.add(recursive(e));
		}
		
		return forms;
	}
	

	public VoteForm recursive(VoteForm form) {
		if(null != form.getTotalVote() && form.getTotalVote() > 0) {
			form.setPercent(NumberUtil.percent(form.getSum() / form.getTotalVote().floatValue(), 0)) ;
		} else {
			form.setPercent("0%") ;
		}
		
		form.setText(form.getSubject()) ;
		List<VoteForm> votes = this.basedaoVote.listSQL("select t.* from ieasy_sys_vote t where t.pid='"+form.getId()+"' order by t.weight asc", VoteForm.class, false) ;
		if(null != votes && votes.size() > 0) {
			
			List<VoteForm> chlds = new ArrayList<VoteForm>() ;
		
			for(VoteForm e : votes) {
				e.setTotalVote(form.getTotalVote());
				VoteForm recursive = this.recursive(e) ;
				
				VoteForm childform = new VoteForm() ;
				BeanUtils.copyNotNullProperties(recursive, childform) ;
				chlds.add(childform) ;
			}
			
			form.setChildren(chlds) ;
		}
		
		return form ;
	}
	
	@Override
	public List<VoteForm> listAll(String pid) {
		String sql = "select t.* from ieasy_sys_vote t where t.pid is null and t.status = false order by t.weight asc" ;
		if(null != pid && !"".equals(pid.trim()))
			sql = "select t.* from ieasy_sys_vote t where t.id='"+pid+"' and t.status = false " ;
		
		List<VoteForm> list = this.basedaoVote.listSQL(sql, VoteForm.class, false) ;
		List<VoteForm> forms = new ArrayList<VoteForm>() ;
		for (VoteForm e : list) {
			forms.add(recursiveForListAll(e));
		}
		return forms;
	}
	
	public VoteForm recursiveForListAll(VoteForm form) {
		form.setText(form.getSubject()) ;
		List<VoteForm> votes = this.basedaoVote.listSQL("select t.* from ieasy_sys_vote t where t.pid='"+form.getId()+"' order by t.weight asc", VoteForm.class, false) ;
		if(null != votes && votes.size() > 0) {
			
			List<VoteForm> chlds = new ArrayList<VoteForm>() ;
		
			for(VoteForm e : votes) {
				VoteForm recursive = this.recursive(e) ;
				
				VoteForm childform = new VoteForm() ;
				BeanUtils.copyNotNullProperties(recursive, childform) ;
				chlds.add(childform) ;
			}
			
			form.setChildren(chlds) ;
		}
		
		return form ;
	}
	
	
	@Override
	public List<VoteForm> getByPid(String pid) {
		Integer totalVote = null ;
		try {
			//总票数
			Map<String, Object> map = this.dbutil.getQr().query("select SUM(t.sum) totalVote from ieasy_sys_vote t where t.pid=?", new MapHandler(), new Object[]{pid}) ;
			if(null != map.get("totalVote")) {
				totalVote = Integer.parseInt(map.get("totalVote").toString()) ;
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		
		
		List<VoteForm> votes = this.basedaoVote.listSQL("select t.* from ieasy_sys_vote t where t.pid='"+pid+"' order by t.weight asc", VoteForm.class, false) ;
		if(null != votes && votes.size() > 0) {
			
			List<VoteForm> chlds = new ArrayList<VoteForm>() ;
		
			for(VoteForm e : votes) {
				
				VoteForm recursive = this.recursive(e) ;
				if(null != totalVote) {
					e.setPercent(NumberUtil.percent(e.getSum() / totalVote.floatValue(), 0)) ;
				}
				
				VoteForm childform = new VoteForm() ;
				BeanUtils.copyNotNullProperties(recursive, childform) ;
				chlds.add(childform) ;
			}
		}
		return votes ;
	}
	
	@Override
	public void closeVote(String id) {
		try {
			this.dbutil.getQr().update("update ieasy_sys_vote t set t.status = (case when t.status=true then false else true end) where t.id=?", new Object[]{id}) ;
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	
	@Override
	public Boolean vote(VoteForm form) {
		try {
			
			//单选
			String sql = "select t.id from ieasy_sys_vote_record t where t.pvid=? and t.ip=?" ;
			Object[] params = new Object[]{form.getPid(), form.getIp()} ;
			//多选
			if(form.isVoteType()) {
				sql = "select t.id from ieasy_sys_vote_record t where t.pvid=? and t.vid=? and t.ip=?" ;
				params = new Object[]{form.getPid(), form.getVid(), form.getIp()} ;
			}
			
			
			Map<String, Object> checkVote = this.dbutil.getQr().query(sql, new MapHandler(), params) ;
			if(null == checkVote) {
				this.dbutil.getQr().update("update ieasy_sys_vote t set t.sum = t.sum+1 where t.id=?", new Object[]{form.getVid()}) ;
				
				
				
				VoteRecordEntity vr = new VoteRecordEntity() ;
				vr.setPvid(form.getPid());
				vr.setVid(form.getVid());
				vr.setIp(form.getIp());
				this.basedaoVoteRecord.add(vr) ;
				
				return true ;
			} else {
				return false ;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 更新位置
	 * @param pid
	 */
	public void updateResetSort(int oldSort, int newSort, String id, String pid) {
		try {
			if(oldSort == newSort) {return;}
			if(oldSort != newSort) {
				if(null == pid || "".equals(pid.trim())) {
					Object[] obj = this.basedaoVote.queryObjectSQL("select min(t.weight) min, max(t.weight) max from ieasy_sys_vote t where t.pid is null") ;
					int min = (int)obj[0] ;
					int max = (int)obj[1] ;
					if(newSort<min) newSort = min;
					if(newSort>=max) newSort = max ;
					
					if(oldSort < newSort) {
						this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight-1 where t.weight>? and t.weight<=? and t.vote.id is null", new Object[]{oldSort, newSort}) ;
					} else {
						this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight+1 where t.weight<? and t.weight>=? and t.vote.id is null", new Object[]{oldSort, newSort}) ;
					}
				} else {
					Object[] obj = this.basedaoVote.queryObjectSQL("select min(t.weight) min, max(t.weight) max from ieasy_sys_vote t where t.pid=?", new Object[]{pid}) ;
					int min = (int)obj[0] ;
					int max = (int)obj[1] ;
					if(newSort<min) newSort = min;
					if(newSort>=max) newSort = max ;
					
					if(oldSort < newSort) {
						this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight-1 where t.weight>? and t.weight<=? and t.vote.id=?", new Object[]{oldSort, newSort, pid}) ;
					} else {
						this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight+1 where t.weight<? and t.weight>=? and t.vote.id=?", new Object[]{oldSort, newSort, pid}) ;
					}
				}
				this.basedaoVote.updateByHql("update VoteEntity t set t.weight=? where t.id=?", new Object[]{newSort, id}) ;
			}
		} catch (Exception e) {
			logger.error("修改排序序号失败：原因：", e) ;
			e.printStackTrace() ;
		}
	}
	
	/**
	 * 获取排序号最小值，最大值
	 * @param pid
	 * @return
	 */
	private Integer[] getMM(String pid) { 
		Integer[] mm = new Integer[2] ;
		if(null == pid || "".equals(pid.trim())) {
			Object[] obj = this.basedaoVote.queryObjectSQL("select min(t.weight) min, max(t.weight) max from ieasy_sys_vote t where t.pid is null") ;
			mm[0] = (int)(obj[0] == null?0:obj[0]) ;
			mm[1] = (int)(obj[1] == null?0:obj[1]) ;
		} else {
			Object[] obj = this.basedaoVote.queryObjectSQL("select min(t.weight) min, max(t.weight) max from ieasy_sys_vote t where t.pid=?", new Object[]{pid}) ;
			mm[0] = (int)(obj[0] == null?0:obj[0]) ;
			mm[1] = (int)(obj[1] == null?0:obj[1]) ;
		}
		return mm;
	}
	
	/**
	 * 添加数据，先将全部元素+1
	 * @param pid
	 */
	private void addResetSort(String pid) {
		if(null == pid || "".equals(pid.trim())) {
			this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight+1 where t.weight>=1 and t.vote.id is null") ;
		} else {
			this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight+1 where t.weight>=1 and t.vote.id=?", new Object[]{pid}) ;
		}
	}
	
	/**
	 * 删除数据，大于原位置的元素全部-1
	 * @param pid
	 */
	private void delResetSort(int oldSort, String pid) {
		if(null == pid || "".equals(pid.trim())) {
			this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight-1 where t.weight>? and t.vote.id is null", new Object[]{oldSort}) ;
		} else {
			this.basedaoVote.updateByHql("update VoteEntity t set t.weight=t.weight-1 where t.weight>? and t.vote.id=?", new Object[]{oldSort, pid}) ;
		}
	}

}
